﻿using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Administration.Claims;
using Microsoft.SharePoint.Utilities;
using System.Web.Security;
using System.DirectoryServices.AccountManagement;

namespace AIS.SharePoint.AspNetFBA.Layouts.AIS.SharePoint.AspNetFBA
{
    public partial class ChangePassword : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                try
                {
                    // Processing: 
                    // 1) Determine claim provider
                    // 2) Extract complexity requirements if FBA claim
                    // 3) Warn if provider is not supported

                    Code.Claims ClaimHandler = new Code.Claims();
                    SPClaim UserClaim = null;
                    try
                    {
                        UserClaim = SPClaimProviderManager.Local.DecodeClaim(Web.CurrentUser.LoginName);
                        txtUserName.Text = UserClaim.Value;
                    }
                    catch
                    {
                        txtUserName.Text = Web.CurrentUser.LoginName;
                    }

                    switch (ClaimHandler.GetAuthenticationModeFromUserClaim(UserClaim))
                    {
                        case System.Web.Configuration.AuthenticationMode.Forms:
                            {
                                lblComplexityOverview.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_ComplexityOverview");
                                lblComplexityDetail.Text = String.Format(Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_ComplexityDetail")
                                    , ClaimHandler.MembershipProvider.MinRequiredPasswordLength
                                    , ClaimHandler.MembershipProvider.MinRequiredNonAlphanumericCharacters);
                                txtCurrentPassword.Focus();
                            }
                            break;

                        case System.Web.Configuration.AuthenticationMode.Windows:
                            {
                                lblComplexityOverview.Text = "";
                                lblComplexityDetail.Text = "";
                                txtCurrentPassword.Focus();
                            }
                            break;

                        default:
                            {
                                lblMasterStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_PasswordChangeNotSupported");
                                uiPasswordChange.Visible = false;
                                uiMasterStatus.Visible = true;
                            }
                            break;
                    }

                }
                catch (Exception ex)
                {
                    Code.Log.Error(ex, Microsoft.SharePoint.Administration.TraceSeverity.High, Code.Log.Category.Processing);
                    SPUtility.TransferToErrorPage(ex.Message);
                }
            }
        }

        public void btnOK_Click(object sender, EventArgs e)
        {
            try
            {
                // Validate the data
                Page.Validate();
                if (!Page.IsValid) { return; }
                if (txtNewPassword.Password != txtNewPasswordConfirm.Password)
                {
                    lblPasswordMatchError.Visible = true;
                    return;
                }
                if (String.IsNullOrEmpty(txtNewPassword.Password)) { return; }

                // Decode the user details
                Code.Claims ClaimHandler = new Code.Claims();
                SPClaim UserClaim = null;
                try { UserClaim = SPClaimProviderManager.Local.DecodeClaim(Web.CurrentUser.LoginName); }
                catch { }
                bool IsPasswordChangeComplete = false;

                switch (ClaimHandler.GetAuthenticationModeFromUserClaim(UserClaim))
                {
                    case System.Web.Configuration.AuthenticationMode.Forms:
                        {
                            try
                            {
                                if (ClaimHandler.MembershipProvider.ChangePassword(UserClaim.Value, txtCurrentPassword.Password, txtNewPassword.Password))
                                {
                                    IsPasswordChangeComplete = true;
                                }
                                else
                                {
                                    lblStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_PasswordChangeFailed");
                                    lblErrorText.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_PasswordChangeFailedCheck");
                                }
                            }
                            catch (Exception ex)
                            {
                                lblStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_PasswordChangeFailed");
                                lblErrorText.Text = ex.Message;
                            }
                        }
                        break;

                    case System.Web.Configuration.AuthenticationMode.Windows:
                        {
                            try
                            {
                                // Attempt to parse the user name
                                // TODO: research better ways to do this code
                                IdentityType ParsedIdentityType = IdentityType.SamAccountName;
                                string ParsedUserName = null;
                                string ParsedDomainName = null;
                                string UserNameToParse = (UserClaim == null ? Web.CurrentUser.LoginName : UserClaim.Value);
                                if (UserNameToParse.Contains("@"))
                                {
                                    // UPN
                                    ParsedIdentityType = IdentityType.UserPrincipalName;
                                    ParsedUserName = UserNameToParse;
                                    ParsedDomainName = UserNameToParse.Split('@')[1];
                                }
                                else if (UserNameToParse.Contains(@"\"))
                                {
                                    // SAM Account Name
                                    ParsedIdentityType = IdentityType.SamAccountName;
                                    string[] SplitName = UserNameToParse.Split('\\');
                                    ParsedUserName = SplitName[1];
                                    ParsedDomainName = SplitName[0];
                                }

                                using (var context = new PrincipalContext(ContextType.Domain, ParsedDomainName, ParsedUserName, txtCurrentPassword.Password))
                                {
                                    using (var user = UserPrincipal.FindByIdentity(context, ParsedIdentityType, ParsedUserName))
                                    {
                                        try
                                        {
                                            user.ChangePassword(txtCurrentPassword.Password, txtNewPassword.Password);
                                            IsPasswordChangeComplete = true;
                                        }
                                        catch (System.DirectoryServices.AccountManagement.PasswordException ex)
                                        {
                                            lblStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_PasswordChangeFailed");
                                            lblErrorText.Text = ex.Message;
                                        }
                                        catch (Exception ex)
                                        {
                                            Code.Log.Error(ex, Microsoft.SharePoint.Administration.TraceSeverity.High, Code.Log.Category.Processing);
                                            lblStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_Error");
                                            lblErrorText.Text = ex.Message;
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                Code.Log.Error(ex, Microsoft.SharePoint.Administration.TraceSeverity.High, Code.Log.Category.Processing);
                                lblStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_Error");
                                lblErrorText.Text = ex.Message;
                            }
                        }
                        break;

                    default:
                        lblStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_PasswordChangeNotSupported");
                        txtCurrentPassword.Enabled = false;
                        txtNewPassword.Enabled = false;
                        txtNewPasswordConfirm.Enabled = false;
                        btnOk.Enabled = false;
                        break;
                }

                if (IsPasswordChangeComplete)
                {
                    lblMasterStatus.Text = Code.Common.GetLocalizedResource("$Resources:Page_ChangePassword_Success");
                    uiPasswordChange.Visible = false;
                    uiMasterStatus.Visible = true;
                }
            }
            catch (Exception ex)
            {
                Code.Log.Error(ex, Microsoft.SharePoint.Administration.TraceSeverity.High, Code.Log.Category.Processing);
                SPUtility.TransferToErrorPage(ex.Message);
            }
        }

        public void btnMasterClose_Click(object sender, EventArgs e)
        {
            Code.Common.ClosePage();
        }
    }
}
